/**
 * 2017年4月23日
 */
package cn.edu.bjtu.asyn.listener;

import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;

import cn.edu.bjtu.asyn.event.BuildLDAEvent;
import cn.edu.bjtu.asyn.event.BuildModelEvet;
import cn.edu.bjtu.asyn.event.BuildWord2VecEvent;
import cn.edu.bjtu.asyn.event.GenericAsynBuildModelEvent;
import cn.edu.bjtu.entity.ExecuteContext;
import cn.edu.bjtu.entity.impl.AsynModelBuildStateSupportExecuteContext;
import cn.edu.bjtu.entity.impl.local.LDABuildExecuteContext;
import cn.edu.bjtu.entity.impl.local.Word2VecBuildExecuteContext;
import service.wechatlab.LabelService;

/**
 * 异步服务
 * 请求微服务,
 * 执行它的线程可能会阻塞很久,所以要异步
 * @author Alex
 *
 */
@SuppressWarnings("rawtypes")
@Component
@EnableAsync
public class BuildModelListener implements ApplicationListener{

	@Autowired LabelService ls;
	public BuildModelListener() {
		// TODO Auto-generated constructor stub
		System.out.println("spring ctor buildmodellistener");
	}
	@Async
	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		// TODO Auto-generated method stub
		if(event instanceof BuildWord2VecEvent || event instanceof BuildLDAEvent ){
			GenericAsynBuildModelEvent gabme = (GenericAsynBuildModelEvent)event;
//			BuildWord2VecEvent eve = (BuildWord2VecEvent)event;
			AsynModelBuildStateSupportExecuteContext ss = (AsynModelBuildStateSupportExecuteContext) gabme.getEc();
			
			//发送HTTP请求给其他,这里估计会持续很久,建立模型要用写锁
			//模型建立之后要把微服务执行的结果存放到数据库里面查看存在的模型的时候通过数据库得到
			//使用trylock,确定当前只有一个线程建立模型,其他请求建立模型的事件会被忽略.
			if(ss.getLock().writeLock().tryLock()){
				System.out.println(Thread.currentThread().getName()+ " have got write lock");
				try{
					ss.executeAsync();
					ss.setSuccess(true);
				}catch(Exception e){
					ss.setMsg(e.getMessage());
					ss.setSuccess(false);
				}finally{
					ss.setExecuting(false);
					System.out.println(Thread.currentThread().getName()+ " release write lock");
					ss.getLock().writeLock().unlock();
				}
			}else{
				System.out.println("model is being built ,skip  thread name: " + Thread.currentThread().getName());
			}
		}else if(event instanceof BuildModelEvet){
			System.out.println(Thread.currentThread().getName());
			System.out.println(ls);
			System.out.println("build model event fired!!!!!!!!");
		}
	}

}
